package com.zxr.demo.application;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private Integer port;

//    @Value("${spring.data.redis.password}")
//    private String password;

    @Value("${spring.data.redis.database}")
    private Integer database;

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }



    private void addMixIn(JsonJacksonCodec jacksonCodec) {
//        jacksonCodec.objectMapper.addMixIn(TaskModel::class.java, TaskModelRedisson::class.java)
//        jacksonCodec.objectMapper.addMixIn(KhlModel::class.java, KhlModelRedisson::class.java)
//        jacksonCodec.objectMapper.addMixIn(UserModel::class.java, UserModelRedisson::class.java)
    }

    /**
     * RedissonClient Bean，使用 Jackson JSON 序列化
     * 用于存储对象
     * @param objectMapper 自动注入的 Jackson ObjectMapper
     * @return RedissonClient
     */
    @Bean(name = {"redisson", "redissonClient"})
    public RedissonClient redisson(ObjectMapper objectMapper) {
        Config config = new Config();
        JsonJacksonCodec jsonJacksonCodec = new JsonJacksonCodec(objectMapper);
        this.addMixIn(jsonJacksonCodec);
        config.setCodec(jsonJacksonCodec);
        SingleServerConfig singleConfig = config.useSingleServer();
        singleConfig.setAddress("redis://" + host + ":" + port);
//        singleConfig.setPassword(password);
        singleConfig.setDatabase(database);
        return Redisson.create(config);
    }

    /**
     * String RedissonClient Bean，使用 String 序列化
     * 用于直接操作字符串
     * @return RedissonClient
     */
    @Bean(name = {"stringRedissonClient"})
    public RedissonClient stringRedisson() {
        Config config = new Config();
        config.setCodec(new StringCodec());
        SingleServerConfig singleConfig = config.useSingleServer();
        singleConfig.setAddress("redis://" + host + ":" + port);
//        singleConfig.setPassword(password);
        singleConfig.setDatabase(database);
        singleConfig.setClientName("stringRedissonClient");
        return Redisson.create(config);
    }

    /**
     * Redisson 提供的 RedisConnectionFactory Bean
     * 它是连接 RedisTemplate 和 StringRedisTemplate 的桥梁
     * @param redisson 自动注入的 RedissonClient Bean
     * @return RedissonConnectionFactory
     */
    @Bean
    @ConditionalOnMissingBean(RedisConnectionFactory.class)
    public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
        return new RedissonConnectionFactory(redisson);
    }

    /**
     * RedisTemplate Bean，用于操作对象
     * 使用 String 序列化键，使用 Jackson 序列化值
     * @param redisConnectionFactory 自动注入的连接工厂
     * @return RedisTemplate
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 配置序列化器，关键步骤
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    /**
     * StringRedisTemplate Bean，用于操作字符串
     * @param redisConnectionFactory 自动注入的连接工厂
     * @return StringRedisTemplate
     */
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}
